using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Security.Cryptography.X509Certificates;
using System.IO;
using System.Xml;
using System.Text;
using StsMngrConfigurationNS;
using System.Configuration;

namespace ManagedCardWriter
{
	public static class ManagedCardWriter
	{
		public static XmlElement CreateCard(bool openid)
		{
			ManagedInformationCard card;
			X509Certificate2 certificate = null;
			InfoCardConfiguration infoCardCfg = openid ?
				StsMngrConfigurationNS.StsMngrConfiguration.Current.OpenIdInfoCard :
				StsMngrConfigurationNS.StsMngrConfiguration.Current.InfoCard;
			try
			{
				card = new ManagedInformationCard((Constants.CardType)Enum.Parse(typeof(Constants.CardType), infoCardCfg.Type));
				card.CardName = infoCardCfg.Details.GetElementByKey("name").Data;
				card.CardId = infoCardCfg.Details.GetElementByKey("id").Data;
				card.CardVersion = infoCardCfg.Details.GetElementByKey("version").Data;
				card.MimeType = "image/png";

				FileInfo file = new FileInfo(infoCardCfg.Details.GetElementByKey("image").Data);
				try
				{
					byte[] data = new byte[file.Length];
					using (FileStream fstream = File.OpenRead(file.FullName))
					{
						fstream.Read(data, 0, data.Length);
						card.CardLogo = data;
					}
				}
				catch (Exception)
				{
					throw new FileLoadException("Exception retrieving the image from: " + file.FullName);
				}

				card.IssuerName = infoCardCfg.Issuer.GetElementByKey("name").Data;
				card.IssuerId = infoCardCfg.Issuer.GetElementByKey("address").Data;
				card.MexUri = infoCardCfg.Issuer.GetElementByKey("mexAddress").Data;
//				card.PrivacyNoticeAt = infoCardCfg.Issuer.GetElementByKey("privacyPolicy").Data;

				StoreName storeName = infoCardCfg.Issuer.GetElementByKey("certificate").StoreName;
				StoreLocation storeLocation = infoCardCfg.Issuer.GetElementByKey("certificate").StoreLocation;

				X509Store store = new X509Store(storeName,storeLocation);
				store.Open(OpenFlags.OpenExistingOnly);

				X509Certificate2Collection collection = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName,
					infoCardCfg.Issuer.GetElementByKey("certificate").Data, true);
				if (collection.Count == 0)
					throw new Exception("Certificate not found: " + infoCardCfg.Issuer.GetElementByKey("certificate").Data);
				certificate = collection[0];

				foreach (CfgElement claim in infoCardCfg.Claims)
					card.SupportedClaims.Add(new ClaimInfo(claim.Key, claim.Data, claim.Edata));

				foreach (CfgElement type in infoCardCfg.TokenTypes)
					card.TokenTypes.Add(type.Data);

				switch (card.CardType)
				{
					case Constants.CardType.UserNamePassword:
						card.CredentialIdentifier = infoCardCfg.Credentials.GetElementByKey("UserNamePassword").Data;
						break;
					case Constants.CardType.SelfIssued:
						card.CredentialIdentifier = infoCardCfg.Credentials.GetElementByKey("SelfIssued").Data;
						break;
					case Constants.CardType.Certificate:
						storeName = infoCardCfg.Credentials.GetElementByKey("certificate").StoreName;
						storeLocation = infoCardCfg.Credentials.GetElementByKey("certificate").StoreLocation;
						store = new X509Store(storeName, storeLocation);
						store.Open(OpenFlags.OpenExistingOnly);

						collection = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName,
							infoCardCfg.Credentials.GetElementByKey("certificate").Data, true);
						if (collection.Count == 0)
							throw new Exception("Certificate not found: " + infoCardCfg.Credentials.GetElementByKey("certificate").Data);
						card.CredentialIdentifier = Convert.ToBase64String(collection[0].GetCertHash());
						break;
				}

				return card.SerializeAndSign(certificate);
			}
			catch( Exception e )
			{
				MessageBox.Show("Exception: " + e.Message);
			}
			return null;
		}
	}
}